package org.linloong.utils;

import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.ClientAbortException;
import org.linloong.config.audio.DifyAgentProperties;
import org.linloong.modules.apis.fire.dto.AudioChatRequest;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * dify智能体调用
 *
 * @Author: kw
 * @date: 2025-10-18 10:05
 */
@Slf4j
public class DifyAgentUtil {
    private static final int timeout = 1000 * 60 * 5;

    public static final Cache<String, String> UPLOAD_CACHE = CacheBuilder.newBuilder()
            .maximumSize(1000) // 设置缓存的最大容量
            .build();

    public static void chat(AudioChatRequest request, HttpServletResponse response, DifyAgentProperties properties, String auth) {
        String params = new JSONObject() {{
            put("query", request.getQuery());
            put("user", properties.getUser());
            put("response_mode", "streaming");
            put("conversation_id", StringUtils.hasText(request.getConversationId()) ? request.getConversationId() : "");
            put("inputs", new JSONObject() {{
                String uploadFileId = request.getUploadFileId();
                String streamId = StringUtils.hasText(request.getStreamId()) ? request.getStreamId() : UPLOAD_CACHE.getIfPresent(uploadFileId);
                if (StringUtils.hasText(streamId)) {
                    put("stream_id", streamId);
                } else {
                    put("input_image", new JSONObject() {{
                        put("type", "image");
                        put("transfer_method", "local_file");
                        put("url", "");
                        put("upload_file_id", uploadFileId);
                    }});
                }
            }});
        }}.toJSONString();
        log.info("params: {}", params);
        try (HttpResponse rsp = HttpRequest.post(properties.getUrl() + "/chat-messages")
                .header("Authorization", "Bearer " + auth)
                .body(params)
                .timeout(timeout)
                .executeAsync()) {
            try (
                    InputStream inputStream = rsp.bodyStream();
                    OutputStream outputStream = response.getOutputStream()
            ) {
                byte[] buffer = new byte[2048];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
//                    log.info("bytesRead: {}", new String(buffer, 0, bytesRead));
                    outputStream.write(buffer, 0, bytesRead);
                    outputStream.flush(); // 确保数据及时发送给客户端
                }
            }
        } catch (ClientAbortException ignored) {
        } catch (IOException e) {
            log.error("IO异常", e);
        }
    }

    public static String uploadFile(String filePath, DifyAgentProperties properties, String auth, String streamId) {
        try (HttpResponse response = HttpRequest.post(properties.getUrl() + "/files/upload")
                .form("file", new File(filePath))
                .form("user", properties.getUser())
                .header("Authorization", "Bearer " + auth)
                .execute()) {
            String uploadFileId = JSON.parseObject(response.body()).getString("id");
            UPLOAD_CACHE.put(uploadFileId, streamId);
            return uploadFileId;
        }
    }

    public static String uploadBase64File(String resultImageBase64, DifyAgentProperties properties, String auth, String streamId) {
        String filePath = null;
        try {
            filePath = Base64ToImage.convertAndSave(resultImageBase64);
            FileUtil.mkParentDirs(new File(filePath));
            return uploadFile(filePath, properties, auth, streamId);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (filePath != null) {
                FileUtil.del(filePath);
            }
        }
    }

    public static String uploadFile(MultipartFile file, DifyAgentProperties properties, String auth) {
        try (InputStream inputStream = file.getInputStream();) {
            try (HttpResponse response = HttpRequest.post(properties.getUrl() + "/files/upload")
                    .form("file", inputStream.readAllBytes(), file.getOriginalFilename())
                    .form("user", properties.getUser())
                    .header("Authorization", "Bearer " + auth)
                    .execute()) {
                log.info("response: {}", response.body());
                return JSON.parseObject(response.body()).getString("id");
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static JSONArray getMessages(String conversationId, DifyAgentProperties properties, String auth) {
        try (HttpResponse response = HttpRequest.get(properties.getUrl() + "/messages")
                .form("user", properties.getUser())
                .form("limit", 100)
                .form("conversation_id", conversationId)
                .header("Authorization", "Bearer " + auth)
                .execute()) {
            log.info("response: {}", response.body());
            return JSON.parseObject(response.body()).getJSONArray("data");
        }
    }

    public static JSONArray getVariables(String conversationId, DifyAgentProperties properties, String auth) {
        try (HttpResponse response = HttpRequest.get(properties.getUrl() + "/conversations/" + conversationId + "/variables")
                .form("user", properties.getUser())
                .header("Authorization", "Bearer " + auth)
                .execute()) {
            log.info("response: {}", response.body());
            return JSON.parseObject(response.body()).getJSONArray("data");
        }
    }

    public static boolean sendWxMessage(String name, String content, DifyAgentProperties properties, String auth) {
        JSONObject params = new JSONObject() {{
            put("inputs", new JSONObject() {{
                put("name", name);
                put("content", content);
            }});
            put("user", properties.getUser());
        }};
        try (HttpResponse response = HttpRequest.post(properties.getUrl() + "/workflows/run")
                .body(params.toJSONString())
                .header("Authorization", "Bearer " + auth)
                .execute()) {
            log.info("response: {}", response.body());
            JSONObject result = JSON.parseObject(response.body());
            if (StringUtils.hasText(result.getString("code"))) {
                throw new RuntimeException(result.getString("message"));
            }
            return true;
        }
    }

    public static boolean sendWxMessage(String content, DifyAgentProperties properties, String auth) {
        return sendWxMessage(properties.getWxUser(), content, properties, auth);
    }

    public static long getWordCache(String link, long wordId) {
        String path = System.getProperty("user.dir") + File.separator + "tempFile" + File.separator + wordId + File.separator + "报告.docx";
        if (FileUtil.exist(path)) {
            log.info("文件已存在：{}", path);
            return wordId;
        }
        FileUtil.mkParentDirs(path);
        try (HttpResponse response = HttpRequest.get(link).execute()) {
            log.info("访问状态码：{}，地址：{}", response.getStatus(), link);
            if (response.getStatus() != 200) {
                return 0;
            }
            FileUtil.writeBytes(response.bodyBytes(), path);
            log.info("文件写到：{}", path);
            return wordId;
        }
    }
}
